import service, { request } from './request'
import { ElMessage, ElMessageBox } from 'element-plus'

/**
 * HTTP工具类
 * 提供常用的HTTP请求方法和工具函数
 */
class HttpUtil {
  constructor() {
    this.service = service
    this.request = request
  }

  /**
   * 并发请求
   * @param {Array} requests 请求数组
   * @param {Object} options 配置选项
   */
  async concurrent(requests, options = {}) {
    const { 
      showLoading = true, 
      loadingText = '加载中...',
      showErrorMsg = true 
    } = options

    try {
      if (showLoading) {
        // 这里可以显示全局loading
      }

      const results = await Promise.allSettled(requests)
      
      const successResults = []
      const errorResults = []

      results.forEach((result, index) => {
        if (result.status === 'fulfilled') {
          successResults.push({
            index,
            data: result.value
          })
        } else {
          errorResults.push({
            index,
            error: result.reason
          })
        }
      })

      if (errorResults.length > 0 && showErrorMsg) {
        ElMessage.warning(`${errorResults.length} 个请求失败`)
      }

      return {
        success: successResults,
        errors: errorResults,
        total: requests.length
      }
    } catch (error) {
      if (showErrorMsg) {
        ElMessage.error('并发请求失败')
      }
      throw error
    }
  }

  /**
   * 重试请求
   * @param {Function} requestFn 请求函数
   * @param {Object} options 配置选项
   */
  async retry(requestFn, options = {}) {
    const { 
      maxRetries = 3, 
      delay = 1000, 
      showRetryMsg = true 
    } = options

    let lastError = null

    for (let i = 0; i <= maxRetries; i++) {
      try {
        const result = await requestFn()
        return result
      } catch (error) {
        lastError = error
        
        if (i < maxRetries) {
          if (showRetryMsg) {
            ElMessage.warning(`请求失败，${delay / 1000}秒后重试... (${i + 1}/${maxRetries})`)
          }
          await this.sleep(delay)
        }
      }
    }

    throw lastError
  }

  /**
   * 轮询请求
   * @param {Function} requestFn 请求函数
   * @param {Function} condition 停止条件函数
   * @param {Object} options 配置选项
   */
  async poll(requestFn, condition, options = {}) {
    const { 
      interval = 2000, 
      maxAttempts = 30,
      showProgress = false 
    } = options

    let attempts = 0

    while (attempts < maxAttempts) {
      try {
        const result = await requestFn()
        
        if (condition(result)) {
          return result
        }

        if (showProgress) {
          ElMessage.info(`轮询中... (${attempts + 1}/${maxAttempts})`)
        }

        await this.sleep(interval)
        attempts++
      } catch (error) {
        console.error('轮询请求失败:', error)
        attempts++
      }
    }

    throw new Error('轮询超时')
  }

  /**
   * 分页请求
   * @param {Function} requestFn 请求函数
   * @param {Object} options 配置选项
   */
  async paginate(requestFn, options = {}) {
    const { 
      pageSize = 20, 
      maxPages = 10,
      autoMerge = true 
    } = options

    const results = []
    let currentPage = 1
    let hasMore = true

    while (hasMore && currentPage <= maxPages) {
      try {
        const response = await requestFn({
          page: currentPage,
          pageSize
        })

        const { data, total, current, size } = response

        if (autoMerge) {
          results.push(...(data || []))
        } else {
          results.push(response)
        }

        // 判断是否还有更多数据
        hasMore = (current * size) < total

        currentPage++
      } catch (error) {
        console.error('分页请求失败:', error)
        break
      }
    }

    return autoMerge ? results : {
      data: results,
      total: results.length
    }
  }

  /**
   * 上传文件（带进度）
   * @param {File} file 文件对象
   * @param {Object} options 配置选项
   */
  async uploadWithProgress(file, options = {}) {
    const { 
      url = '/file/upload',
      onProgress,
      showProgress = true 
    } = options

    const formData = new FormData()
    formData.append('file', file)

    return this.request.upload(url, formData, {
      onUploadProgress: (progressEvent) => {
        const percentCompleted = Math.round(
          (progressEvent.loaded * 100) / progressEvent.total
        )

        if (showProgress) {
          ElMessage.info(`上传进度: ${percentCompleted}%`)
        }

        if (onProgress) {
          onProgress(percentCompleted, progressEvent)
        }
      }
    })
  }

  /**
   * 下载文件
   * @param {string} url 下载地址
   * @param {string} filename 文件名
   * @param {Object} options 配置选项
   */
  async downloadFile(url, filename, options = {}) {
    const { 
      showProgress = true,
      params = {} 
    } = options

    try {
      const response = await this.request.download(url, params, {
        onDownloadProgress: (progressEvent) => {
          if (showProgress && progressEvent.lengthComputable) {
            const percentCompleted = Math.round(
              (progressEvent.loaded * 100) / progressEvent.total
            )
            ElMessage.info(`下载进度: ${percentCompleted}%`)
          }
        }
      })

      // 创建下载链接
      const blob = new Blob([response.data])
      const downloadUrl = window.URL.createObjectURL(blob)
      const link = document.createElement('a')
      link.href = downloadUrl
      link.download = filename || 'download'
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)
      window.URL.revokeObjectURL(downloadUrl)

      ElMessage.success('下载完成')
    } catch (error) {
      ElMessage.error('下载失败')
      throw error
    }
  }

  /**
   * 确认请求（带确认对话框）
   * @param {Function} requestFn 请求函数
   * @param {Object} options 配置选项
   */
  async confirmRequest(requestFn, options = {}) {
    const {
      title = '确认操作',
      message = '确定要执行此操作吗？',
      confirmButtonText = '确定',
      cancelButtonText = '取消',
      type = 'warning'
    } = options

    try {
      await ElMessageBox.confirm(message, title, {
        confirmButtonText,
        cancelButtonText,
        type
      })

      return await requestFn()
    } catch (error) {
      if (error === 'cancel') {
        ElMessage.info('已取消操作')
        return null
      }
      throw error
    }
  }

  /**
   * 批量请求（串行）
   * @param {Array} requests 请求数组
   * @param {Object} options 配置选项
   */
  async batchSerial(requests, options = {}) {
    const { 
      showProgress = true,
      stopOnError = false 
    } = options

    const results = []
    
    for (let i = 0; i < requests.length; i++) {
      try {
        if (showProgress) {
          ElMessage.info(`处理中... (${i + 1}/${requests.length})`)
        }

        const result = await requests[i]()
        results.push({
          index: i,
          success: true,
          data: result
        })
      } catch (error) {
        results.push({
          index: i,
          success: false,
          error
        })

        if (stopOnError) {
          break
        }
      }
    }

    return results
  }

  /**
   * 延迟函数
   * @param {number} ms 延迟毫秒数
   */
  sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms))
  }

  /**
   * 格式化文件大小
   * @param {number} bytes 字节数
   */
  formatFileSize(bytes) {
    if (bytes === 0) return '0 Bytes'
    
    const k = 1024
    const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']
    const i = Math.floor(Math.log(bytes) / Math.log(k))
    
    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
  }

  /**
   * 检查网络状态
   */
  checkNetworkStatus() {
    return navigator.onLine
  }

  /**
   * 获取请求配置
   */
  getRequestConfig() {
    return {
      baseURL: process.env.VUE_APP_BASE_API,
      timeout: 15000,
      withCredentials: true
    }
  }
}

// 创建实例
const http = new HttpUtil()

// 导出实例和类
export default http
export { HttpUtil }
